#include "functionedit.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QIcon>
#include <QMessageBox>

#include "analitza/analitza.h"
#include "analitza/expression.h"
#include "plotView.h"
#include "algebrahighlighter.h"
#include "analitza/variables.h"
#include "functionsmodel.h"

FunctionEdit::FunctionEdit(QWidget *parent, Qt::WFlags f) :
		QWidget(parent, f), m_correct(false)
{
        this->setWindowTitle(QString("Add/Edit a function"));
	QVBoxLayout *topLayout = new QVBoxLayout(this);
	topLayout->setMargin(2);
	topLayout->setSpacing(5);
	
        m_name = new QLineEdit(this);
	
	m_func = new ExpressionEdit(this);
	m_func->setAns("x");
	connect(m_func, SIGNAL(textChanged()), this, SLOT(edit()));
	connect(m_func, SIGNAL(returnPressed()), this, SLOT(ok()));
	
	m_valid = new QLabel(this);
	m_valid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
	m_validIcon = new QLabel(this);
	m_validIcon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
	QLayout* validLayout=new QHBoxLayout;
	validLayout->addWidget(m_validIcon);
	validLayout->addWidget(m_valid);
	
        m_color = new ColorCombo(this);
	m_color->setColor(QColor(0,150,0));
	connect(m_color, SIGNAL(currentIndexChanged(int)), this, SLOT(colorChange(int)));
	
	m_funcsModel=new FunctionsModel;
        m_graph = new PlotView(m_funcsModel, this);
	m_graph->setViewport(QRect(QPoint(-5, 7), QPoint(5, -7)));
	m_graph->setResolution(200);
	m_graph->setFocusPolicy(Qt::NoFocus);
	m_graph->setMouseTracking(false);
	m_graph->setFramed(true);
	m_graph->setReadOnly(true);
	m_graph->setSquares(false);
	
	QHBoxLayout *m_butts = new QHBoxLayout(0);
	topLayout->addWidget(m_name);
	topLayout->addWidget(m_func);
	topLayout->addWidget(m_color);
	topLayout->addLayout(validLayout);
	topLayout->addWidget(m_graph);
	topLayout->addLayout(m_butts);
	
        m_name->hide(); //FIXME: Remove this when the name has any sense
	m_func->setFocus();
}

FunctionEdit::~FunctionEdit()
{}


void FunctionEdit::clear()
{
	m_func->setText(QString());
	m_funcsModel->clear();
	edit();
}

void FunctionEdit::setText(const QString &newText)
{
	m_func->setText(newText);
	m_func->document()->setModified(true);
}

void FunctionEdit::setColor(const QColor &newColor)
{
	m_color->setColor(newColor);
	if(m_funcsModel->rowCount()>0)
		  m_funcsModel->editFunction(0)->setColor(newColor);
	m_graph->forceRepaint();
}

void FunctionEdit::colorChange(int)
{
	setColor(m_color->color());
}

void FunctionEdit::edit()	//Let's see if the exp is correct
{
    Analitza a;
    QString funct = m_func->text();
    QStringList bvl;

    if(m_func->text().isEmpty()) {
        m_func->setCorrect(true);
        m_valid->setText(QString());
        m_validIcon->setPixmap(QIcon("flag-yellow").pixmap(QSize(16,16)));
        return;
    }
    if(!m_func->isMathML())
        a.setExpression(Expression(funct, 0));
    else
        a.setExpression(Expression(funct, 1));

    Expression res;
    bool bvarCorrect=true;
    if(a.isCorrect()) {
        bvl = a.bvarList();
        QString var = bvl.isEmpty() ? "x" : bvl[0];

        if(function::supportedBoundedVars().contains(var)) {
            a.insertVariable(var, Cn(0.));
        } else
        {
            bvarCorrect=false;
        }

        res=a.calculate();
    }
    else
        a.errors() << QString("From parser:") << a.expression()->error();

    m_correct= bvarCorrect && a.isCorrect() && res.isValue();
    function f;
    if(m_correct) {
        f=function(m_name->text(), m_func->expression(), m_color->color());
        f.update_points(QRect(-10, 10, 10, -10), 100);
    }
    m_correct=m_correct && f.isCorrect();

    if(m_correct) {
        m_funcsModel->clear();
        m_funcsModel->addFunction(f);
        m_valid->setToolTip(QString());
        m_valid->setText(QString("<b style='color:#090'>%1:=%2</b>").arg(m_name->text()).arg(a.expression()->toString()));
        m_validIcon->setPixmap(QIcon("flag-green").pixmap(QSize(16,16)));

    } else
    {
        QStringList errors=a.errors();
        if(a.isCorrect() && !res.isValue())
            errors.append(QString("We can only draw Real results."));
        else if(!bvarCorrect)
            errors.append(QString("Error message. Unknown bounded variable: %1").arg(bvl.join(", ")));
        errors += f.errors();
        m_funcsModel->clear();
        m_valid->setText(QString("<b style='color:red'>%1</b>").arg(errors.first()));
        m_valid->setToolTip(errors.join("\n"));
        m_validIcon->setPixmap(QIcon("flag-red").pixmap(QSize(16,16)));
    }
    m_graph->forceRepaint();
    m_func->setCorrect(m_correct);
}

void FunctionEdit::ok()
{
    if(m_correct)
        emit accept();
}

void FunctionEdit::focusInEvent(QFocusEvent *)
{
    m_func->setFocus();
}


//////////////////////////////////////////
///////////ColorCombo is deprecated.//////
ColorCombo::ColorCombo(QWidget* parent) : QComboBox(parent)
{
    setIconSize(QSize(width()*2, QFontMetrics(font()).height()));
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    addItem(tr("Màu khác..."));
    setColor(Qt::green);
    setColor(Qt::black);
    setColor(Qt::blue);
    setColor(Qt::red);
}

void ColorCombo::resizeEvent(QResizeEvent * e)
{
	QWidget::resizeEvent(e);
	QSize s = QSize(width(), QFontMetrics(font()).height()+2);
}

void ColorCombo::setColor(const QColor &color)
{
	int pos = findData(color.name());
	if(pos==-1) {
		QPixmap p(iconSize());
		p.fill(color);
		addItem(p, QString(), color.name());
		setCurrentIndex(count()-1);
	} else {
		setCurrentIndex(pos);
	}
}

QColor ColorCombo::color() const
{
    if(this->currentText() == tr("Màu khác..."))
    {
        QColor newColor;
        newColor = QColorDialog::getColor();
        if(newColor.isValid())
        {
            return newColor;
        }
    }
    return QColor(itemData(currentIndex()).toString());
}

